package com.robotserver.orders.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.kplunion.OrderService.request.query.OrderRowReq;
import com.jd.open.api.sdk.domain.kplunion.OrderService.response.query.OrderRowQueryResult;
import com.jd.open.api.sdk.domain.kplunion.OrderService.response.query.OrderRowResp;
import com.jd.open.api.sdk.request.kplunion.UnionOpenOrderRowQueryRequest;
import com.jd.open.api.sdk.response.kplunion.UnionOpenOrderRowQueryResponse;
import com.robotserver.orders.common.DateFormatUtil;
import com.robotserver.orders.common.DateUtil;
import com.robotserver.orders.constant.CacheKey;
import com.robotserver.orders.constant.ResponseCode;
import com.robotserver.orders.entity.JdOrders;
import com.robotserver.orders.entity.JdTokens;
import com.robotserver.orders.exception.BusinessException;
import com.robotserver.orders.mapper.JdOrdersMapper;
import com.robotserver.orders.mapper.JdTokensMapper;
import com.robotserver.orders.mapper.SysSettingMapper;
import com.robotserver.orders.param.JdOrderApiPullDto;
import com.robotserver.orders.param.JdOrderSyncParam;
import com.robotserver.orders.param.biz.JdOrderPullParam;
import com.robotserver.orders.service.JdOrderService;
import com.robotserver.orders.service.JdOrderSyncService;
import com.robotserver.orders.vo.JdOrderApiPullVo;
import com.robotserver.orders.vo.JdOrderTimeVO;
import com.robotserver.orders.vo.biz.JdOrderVO;
import com.robotserver.orders.vo.biz.PageVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @Auther: jianghan
 * @Date: 2019/11/13 17:05
 * @Description:
 */
@Service
public class JdOrderServiceImpl implements JdOrderService {

    private static Logger logger = LoggerFactory.getLogger(JdOrderServiceImpl.class);

    @Autowired
    private JdOrderSyncService jdOrderSyncService;

    @Autowired
    private SysSettingMapper sysSettingMapper;
    @Autowired
    private JdTokensMapper jdTokensMapper;
    @Autowired
    private JdOrdersMapper jdOrdersMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${jd.sdk.url}")
    private String jdSdkUrl;
    @Value("${cluster.group}")
    private String clusterGroup;
    private static int threadRatio = 20;    // 线程比例
    @Override
    public void syncOrder(JdOrderSyncParam jdOrderSyncParam) {
        try {
            List<JdOrderTimeVO> jdOrderTimeScope = DateUtil.getJdOrderTimeScope_ByAppKey(jdOrderSyncParam.getBegin_time(),jdOrderSyncParam.getEnd_time());

            String jd_appkeys = sysSettingMapper.getByKey("jd_appkey");
            String jd_appsecrets = sysSettingMapper.getByKey("jd_appsecret");

            String[] aks = getAppkey(jd_appkeys,jd_appsecrets);
            String jd_appkey = aks[0];
            String jd_appsecret = aks[1];

            List<JdTokens> jdTokens = new ArrayList<>();
            if (StringUtils.isNotBlank(jdOrderSyncParam.getAuthKey())){
                JdTokens jdToken = new JdTokens();
                jdToken.setUnionId(jdOrderSyncParam.getUnionId());
                jdToken.setAuthKey(jdOrderSyncParam.getAuthKey());
                jdToken.setId(jdOrderSyncParam.getTokenId());
                jdToken.setType(jdOrderSyncParam.getType());
                jdTokens.add(jdToken);
            }else {
                int now = DateUtil.getNowTime();
                int validTime = now-172800; // 两天内修改的token都需要同步
                int count = jdTokensMapper.getCount(validTime);
                String[] serInfo = clusterGroup.split("_");
                int serCount = Integer.parseInt(serInfo[0]);
                int serInd = Integer.parseInt(serInfo[1]);
                if (count!=0){
                    int jdtokenCount = count/serCount;
                    int jdtokenInd = (jdtokenCount*serInd);
                    if (serInd == serCount-1){
                        jdtokenCount = jdtokenCount+(count%serCount);
                    }
                    jdTokens = jdTokensMapper.getTokens(validTime,jdtokenInd,jdtokenCount);
                }
                /*if (serInd==0){
                    JdTokens jdToken = new JdTokens();
                    jdToken.setUnionId("1000000000");
                    jdToken.setAuthKey("f5ca2c063d6747d696524de8f206035f");
                    jdToken.setId(jdOrderSyncParam.getTokenId());
                    jdToken.setType(2);
                    jdTokens.add(jdToken);
                }*/
            }


            int threadCount = (jdTokens.size()/threadRatio)+1;
            String lock = clusterGroup+"_jd_order_lock_"+ IdWorker.getId();
            logger.info(lock+">>jdtokens size:{}",jdTokens.size());
            JdClient client=new DefaultJdClient(jdSdkUrl,"",jd_appkey,jd_appsecret,5000,5000);
            for (int i=0;i<threadCount;i++){
                jdOrderSyncService.threadSyncOrder(jdTokens,jdOrderTimeScope,client,lock);
            }
        } catch (Exception e) {
            logger.error("sync err:{}",e);
        }
    }

    @Override
    public PageVO getOrderList(JdOrderPullParam param) {
        List<JdOrders> list = jdOrdersMapper.getOrderList(param);
        JdOrderVO jdOrderVO = new JdOrderVO();
        jdOrderVO.setRecords(list);
        return jdOrderVO;
    }

    @Override
    public List<JdOrders> getByOrderId(String orderId) {
        return jdOrdersMapper.getListByOrderId(orderId);
    }

    @Override
    public JdOrders getByordAndSku(Long order_id, Long sku_id,Long createdt,String unionId,String authKey) {

        if (createdt!=null && createdt.longValue()>0 && StringUtils.isNotBlank(unionId) && StringUtils.isNotBlank(authKey)){
            String jd_appkey = sysSettingMapper.getByKey("jd_appkey");
            String jd_appsecret = sysSettingMapper.getByKey("jd_appsecret");
            JdClient client=new DefaultJdClient(jdSdkUrl,"",jd_appkey,jd_appsecret);

            try {
                long time = createdt.longValue()*1000;
                String timeStr  = DateFormatUtil.format(new Date(time),"yyyyMMddHHmm");

                //去掉最后时间字符串最后两位
                String timeStrTmp = timeStr = timeStr.substring(0,timeStr.length()-2);
                //拼开始时间
                String startdate = timeStrTmp + "00";
                //拼结束时间
                String enddate = timeStrTmp + "59";

                //UnionOpenOrderQueryRequest request = new UnionOpenOrderQueryRequest();
                UnionOpenOrderRowQueryRequest request=new UnionOpenOrderRowQueryRequest();
                //OrderReq orderReq=new OrderReq();
                OrderRowReq orderReq=new OrderRowReq();
                orderReq.setPageIndex(1);
                orderReq.setPageSize(100);
                orderReq.setType(1);
                orderReq.setStartTime(startdate);
                orderReq.setEndTime(enddate);
                orderReq.setKey(authKey);
                orderReq.setFields("goodsInfo,categoryInfo"); //筛选出参，多项逗号分隔，目前支持：categoryInfo、goodsInfo
                request.setOrderReq(orderReq);
                //UnionOpenOrderQueryResponse response=client.execute(request);
                UnionOpenOrderRowQueryResponse response=client.execute(request);
                if(response != null){
                    OrderRowQueryResult queryResult = response.getQueryResult();
                    if(queryResult != null){
                        // 处理订单入库
                        jdOrderSyncService.ordersAdd(queryResult.getData());
                    }
                }
            } catch (Exception e) {
                logger.error("jd sync order err:",e);
            }
        }
        return jdOrdersMapper.getByordAndSku(order_id,sku_id);
    }

    private String[] getAppkey(String appkeys,String appsecrets){
        String[] appkeyArray = appkeys.split(",");
        String[] appsecretsArray = appsecrets.split(",");
        String[] aks = new String[2];

        try {
            Random random = new Random();
            int index = random.nextInt(appkeyArray.length);
            aks[0] = appkeyArray[index];
            aks[1] = appsecretsArray[index];
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtils.isBlank(aks[0]) || StringUtils.isBlank(aks[1])){
            aks[0] = appkeyArray[0];
            aks[1] = appsecretsArray[0];
        }
        return aks;
    }

    @Async("taskExecutor")
    @Override
    public void syncOrder_producer(JdOrderSyncParam jdOrderSyncParam) {
        try {
            //查询两天内修改的京东token
            int now = DateUtil.getNowTime();
            int validTime = now-172800; // 两天内修改的token都需要同步
            List<JdTokens> jdTokensList = jdTokensMapper.getAllTokens(validTime);
            //往redis队列中塞阿里妈妈tokens
            for (JdTokens jdTokens : jdTokensList) {
                jdTokens.setBeginTime(jdOrderSyncParam.getBegin_time());
                jdTokens.setEndTime(jdOrderSyncParam.getEnd_time());
                //对象转成JSON字符串，保存到redis队列中
                String jdTokensStr =  JSONObject.toJSONString(jdTokens);
                redisTemplate.opsForList().leftPush(jdOrderSyncParam.getRedisQueueKey(), jdTokensStr);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Async("taskExecutor")
    @Override
    public void syncOrder_consumer(JdOrderSyncParam jdOrderSyncParam) {

        String jd_appkeys = sysSettingMapper.getByKey("jd_appkey");
        String jd_appsecrets = sysSettingMapper.getByKey("jd_appsecret");

        String[] aks = getAppkey(jd_appkeys,jd_appsecrets);
        String jd_appkey = aks[0];
        String jd_appsecret = aks[1];

        JdClient client = new DefaultJdClient(jdSdkUrl,"",jd_appkey,jd_appsecret,15000,5000);

        while (true) {
            try {
                //从redis队列中获取联盟
                Object jdTokensObject = redisTemplate.opsForList().rightPop(jdOrderSyncParam.getRedisQueueKey());
                if (jdTokensObject != null) {
                    JdTokens jdTokens = JSONObject.parseObject(jdTokensObject.toString(),JdTokens.class);
                    //封装分段时间查询参数
                    List<JdOrderTimeVO> jdOrderTimeScope = DateUtil.getJdOrderTimeScope_ByAppKey(jdTokens.getBeginTime(),jdTokens.getEndTime());
                    jdOrderSyncService.threadSyncOrder_consumer(jdTokens,jdOrderTimeScope,client);
                    //暂停10毫秒
                    Thread.sleep(10);
                }else{
                    // 没有需要处理的数据了
                    logger.info("-------------------------京东联盟队列已经消费完成---------------！");
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 通过工具商获取京东订单
     */
    @Async("taskExecutor")
    @Override
    public void syncOrder_byAppKey(JdOrderSyncParam jdOrderSyncParam) {

        List<JdOrderTimeVO> jdOrderTimeScope = DateUtil.getJdOrderTimeScope_ByAppKey(jdOrderSyncParam.getBegin_time(),jdOrderSyncParam.getEnd_time());
        String jd_appkeys = sysSettingMapper.getByKey("jd_appkey");
        String jd_appsecrets = sysSettingMapper.getByKey("jd_appsecret");

        //随机取一个
//        String[] aks = getAppkey(jd_appkeys, jd_appsecrets);
//        String jd_appkey = aks[0];
//        String jd_appsecret = aks[1];
//        JdClient client = new DefaultJdClient(jdSdkUrl,"",jd_appkey,jd_appsecret,5000,5000);

        //二个都要拉取
        String[] jdAppKeyArr = jd_appkeys.split(",");
        String[] jdAppsecretArr = jd_appsecrets.split(",");

        logger.info("---------京东通过工具商AppKey拉取订单-------开始------");

        if(jdAppKeyArr != null && jdAppsecretArr != null && jdAppKeyArr.length == jdAppsecretArr.length) {
            for (int i = 0; i < jdAppKeyArr.length; i++) {
                try {
                    JdClient client = new DefaultJdClient(jdSdkUrl,"", jdAppKeyArr[i], jdAppsecretArr[i] ,5000,5000);
                    jdOrderSyncService.threadSyncOrder_byAppKey(jdOrderTimeScope, client, jdOrderSyncParam.getDownTimeType());
                }catch (Exception e){
                    logger.error("---京东联盟下载失败，jdAppKey={},jdAppsecret={}", jdAppKeyArr[i], jdAppsecretArr[i]);
                }
            }
        }
        logger.info("---------京东通过工具商AppKey拉取订单-------结束----");
    }


    /**
     * 通过工具商获取京拥订单
     */
    @Async("taskExecutor")
    @Override
    public void syncJyOrder_byAppKey(JdOrderSyncParam jdOrderSyncParam) {
        List<JdOrderTimeVO> jdOrderTimeScope = DateUtil.getJdOrderTimeScope_ByAppKey(jdOrderSyncParam.getBegin_time(),jdOrderSyncParam.getEnd_time());
        jdOrderSyncService.threadSyncJyOrder_byAppKey(jdOrderTimeScope);
    }

    /**
     * 补单拉取京东订单-生产者-往redis队列当中生产
     */
    @Async("taskExecutor")
    @Override
    public void syncOrder_byAppKey_producer(JdOrderSyncParam jdOrderSyncParam) {
        List<JdOrderTimeVO> jdOrderTimeScope = DateUtil.getJdOrderTimeScope_ByAppKey(jdOrderSyncParam.getBegin_time(),jdOrderSyncParam.getEnd_time());
        //对象转成JSON字符串，保存到redis队列中
        //往redis队列中塞阿里妈妈tokens
        if(jdOrderTimeScope != null && jdOrderTimeScope.size() > 0){
            for (JdOrderTimeVO jdOrderTimeVO : jdOrderTimeScope) {
                jdOrderTimeVO.setDownTimeType(jdOrderSyncParam.getDownTimeType());
                String jdOrderTimeVOStr = JSONObject.toJSONString(jdOrderTimeVO);
                redisTemplate.opsForList().leftPush(CacheKey.jdAppkeyOrderQueue, jdOrderTimeVOStr);
            }

        }
    }

    @Async("taskExecutor")
    @Override
    public void syncOrder_byAppKey_consumer(JdOrderSyncParam jdOrderSyncParam) {

        String jd_appkeys = sysSettingMapper.getByKey("jd_appkey");
        String jd_appsecrets = sysSettingMapper.getByKey("jd_appsecret");

        //随机取一个
//        String[] aks = getAppkey(jd_appkeys, jd_appsecrets);
//        String jd_appkey = aks[0];
//        String jd_appsecret = aks[1];
//        JdClient client = new DefaultJdClient(jdSdkUrl,"",jd_appkey,jd_appsecret,5000,5000);


        //二个都要拉取
        String[] jdAppKeyArr = jd_appkeys.split(",");
        String[] jdAppsecretArr = jd_appsecrets.split(",");

        while (true) {
            try {
                //从redis队列中获取联盟
                Object jdTokensObject = redisTemplate.opsForList().rightPop(jdOrderSyncParam.getRedisQueueKey());
                if (jdTokensObject != null) {
                    if(jdAppKeyArr != null && jdAppsecretArr != null && jdAppKeyArr.length == jdAppsecretArr.length){
                        for (int i = 0; i < jdAppKeyArr.length; i++) {
                            try {
                                JdClient client = new DefaultJdClient(jdSdkUrl,"", jdAppKeyArr[i], jdAppsecretArr[i] ,5000,5000);
                                JdOrderTimeVO jdOrderTimeVO = JSONObject.parseObject(jdTokensObject.toString(),JdOrderTimeVO.class);

                                Integer downTimeType = jdOrderTimeVO.getDownTimeType();
                                if(downTimeType == null){
                                    downTimeType = 3; //订单更新时间
                                }

                                jdOrderSyncService.threadSyncJyOrder_byAppKey_consumer(jdOrderTimeVO,client, downTimeType);
                                //暂停10毫秒
                                Thread.sleep(10);
                            }catch (Exception e){
                                // 没有需要处理的数据了
                                logger.error("--补拉订单订单订单出错--jdAppKey={},jdAppsecret={}", jdAppKeyArr[i], jdAppsecretArr[i]);
                            }
                        }
                    }
                }else{
                    // 没有需要处理的数据了
                    logger.info("-------------------------补拉京东Redis队列已经消费完成---------------！");
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 直接从京东API拉去订单
     * @author jitwxs
     * @date 2022/11/3 19:44
     */
    public PageVO apiPull(JdOrderApiPullDto jdOrderApiPullDto){

        logger.info("京东订单下载接口，para={}",JSONObject.toJSONString(jdOrderApiPullDto));

        if (jdOrderApiPullDto.getEndTime() == null
                || jdOrderApiPullDto.getBeginTime() == null
                || jdOrderApiPullDto.getQueryType() == null
                || StringUtils.isBlank(jdOrderApiPullDto.getAppkey())
                || StringUtils.isBlank(jdOrderApiPullDto.getAppsecret())
        ){
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "参数错误");
        }

        //判断开始时间是否小于90天前
        Integer now = DateUtil.getNowTime();
        if(jdOrderApiPullDto.getBeginTime() < (Long.valueOf(now)-7776000)){
            logger.error("------远程拉取淘宝订单V3版本错误，开始时间不能小于90天前。-------" + jdOrderApiPullDto.getBeginTime() + "::" + jdOrderApiPullDto.getEndTime());
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "拉取订单开始时间不能小于90天前");
        }

        //时间段不能超过20分钟
        if(jdOrderApiPullDto.getEndTime().intValue() - jdOrderApiPullDto.getBeginTime().intValue() > 20 * 60){
            logger.error("------远程拉取淘宝订单V3版本错误，拉取时间段只能为20分钟之内。-------" + jdOrderApiPullDto.getBeginTime() + "::" + jdOrderApiPullDto.getEndTime());
            throw new BusinessException(ResponseCode.BUSINESS_EXCEPTION, "拉取时间段只能为20分钟之内");
        }

        return jdOrderSyncService.apiPull_byAppKey(jdOrderApiPullDto);
    }



}
